#include "visualisation.h"
#include "myapplication.h"
#include <iostream>

using namespace std;
using namespace Ogre;


Visualisation::Visualisation() : myApp(NULL)
{
	construction_finie=false;
	decalage=0;
}

Visualisation::~Visualisation()
{
	delete myApp;
}

void Visualisation::setApplication(MyApplication * m)
{
	myApp = new MyApplication;
	myApp = m;
}

//fonction permettant d'afficher un message dans le panneau d'affichage
void Visualisation::afficherMessage ( string s )
{
    myApp->setDebugOverlay(s) ;;
}

//fonction pour tracer une ligne entre 2 objets
void Visualisation::ligne(SceneNode* sceneN,Vector3 pos1, Vector3 pos2) {
    ManualObject* myManualObject =  myApp->getSceneManager()->createManualObject("Ligne" + myApp->getNbLignes());
    SceneNode* myManualObjectNode = sceneN->createChildSceneNode("LigneNode" + myApp->getNbLignes());


    myManualObject->begin("Color/Black" , Ogre::RenderOperation::OT_LINE_LIST);
    myManualObject->position(pos1);
    myManualObject->position(pos2);
    myManualObject->end();

    myManualObjectNode->attachObject(myManualObject);

    myApp->setNbLignes(myApp->getNbLignes()+1);
}

//on créé le noeud racine de l'application sur lequel tous les autres noeuds seront rattachés
void Visualisation::creerRacine(string nom, string nomMesh, Vector3 echelle)
{
    Entity * ent = myApp->getSceneManager()->createEntity(nom,nomMesh);
    SceneNode* node = myApp->getSceneManager()->getRootSceneNode()->createChildSceneNode(nom);
    node->scale(echelle);
    node->attachObject(ent);
	//on recupere le rayon du premier cube
    myApp->setRatio(myApp->getSceneManager()->getEntity(nom)->getBoundingRadius());
	//selection initiale
    myApp->setSelected(nom);
	this->racine=node;
}

void Visualisation::creerEntite(string nom, string nomMesh, Vector3 position)
{
	Entity * ent = myApp->getSceneManager()->createEntity(nom,nomMesh);
    SceneNode* node = this->racine->createChildSceneNode(nom,(position*FACTOR));
	node->scale(Vector3(SCALE,SCALE,SCALE));
    node->attachObject(ent);
}

//repartit les elements horizontalement dans l'espace
//on fournira uniquement des espacements impaires
void Visualisation::repartirAbscisse( int espacement_horizontal,int espacement_vertical, int profondeur, vector<Vector3> &vectPositions)
{
	vectPositions[0]=Vector3(getDecalage(),profondeur+espacement_vertical,0);
	for (unsigned int i=1;i<vectPositions.size();i++)
	{
		vectPositions[i] = Vector3((vectPositions[0]).x + i*(espacement_horizontal+1),profondeur+espacement_vertical,0);
	}
	decalage=((int)(vectPositions[vectPositions.size()-1].x))+5*espacement_horizontal;

	//DEBUG
	ostringstream oss;
	oss<<(int)vectPositions[vectPositions.size()-1].x<<endl;
	afficherMessage(oss.str());
}

//affiche les fils d'un repertoire
void Visualisation::afficherFils(Folder * dossierPere, Vector3 positionPere,vector<Vector3> &vectPositions)
{
		unsigned int i;
		unsigned int fin_fichier_gauche;
		//affichage de la moitie des fichiers sur la gauche
		for (i=0,fin_fichier_gauche=0; i< (dossierPere->getLeftFiles()).size();i++,fin_fichier_gauche++)
		{
			creerEntite((dossierPere->getFileNo(i))->getNom(),"SphereRed.mesh",vectPositions[i]);
		}
		//affichage des sous-repertoires au centre
		for (unsigned int j=0; j< (dossierPere->getOrderedSubfolders()).size();i++,j++)
		{
			creerEntite((dossierPere->getFolderNo(j))->getNom(),"CubeGreen.mesh",vectPositions[i]);
		}
		//affichage de la moitie des fichiers sur la droite
		for (unsigned int k=0; k< (dossierPere->getRightFiles()).size();i++,k++)
		{
			creerEntite((dossierPere->getFileNo(k+fin_fichier_gauche))->getNom(),"SphereBlue.mesh",vectPositions[i]);
		}
} 

void Visualisation::creerLiensFils(Vector3 position, vector<Vector3> &vectPositions) 
{
	for (unsigned int i=0;i<vectPositions.size();i++)
	{
		ligne(getRacine(),position,vectPositions[i]);
	}
}

Vector3 Visualisation::positionnerElements(Folder * f)
{
	//debug
	ostringstream oss;


	//on recupere les sous-repertoires
	int ma_position_x;
	Vector3 maPosition; 
	vector<Folder *> repertoiresFils = f->getOrderedSubfolders();
	vector<Vector3> vectPosFils(f->objCount);

	// !(f->queDesFilsTerminaux) pour debug !!
	if ( (f->queDesFilsTerminaux) )
	{
		debug+="Cas 1\n";
		afficherMessage("cas1");
		//on recupere la position a laquelle doit se placer les fils
		repartirAbscisse(3*SCALE,5*SCALE,(f->getProfondeur())+1,vectPosFils);
		//on calcul la position du pere en fonction de la position des fils
		ma_position_x=(((int)vectPosFils[vectPosFils.size()-1].x)-((int)vectPosFils[0].x))/2;

	//DEBUG
		/*ostringstream oss;
		oss<<ma_position_x;
		afficherMessage(oss.str());*/


		maPosition=Vector3(ma_position_x,f->getProfondeur(),0);

	//debug
		oss<<f->getProfondeur();
		debug+="prof avant"+oss.str()+"\n";


		//on affiche le pere 	
		creerEntite(f->getNom(),"CubeYellow.mesh",maPosition);	
		//on affiche les fils
		afficherFils(f,maPosition,vectPosFils);
		//creation des liens avec les fils
		creerLiensFils(maPosition,vectPosFils);
	}
	else
	{
		//DEBUG
		debug+="Cas 2\n";
		oss<<repertoiresFils.size()<<endl;
		debug+=oss.str();
		for (unsigned int i=0; i<repertoiresFils.size() ; i++)
		{
			debug+=(repertoiresFils[i]->getNom());
		}
	
		//ajout dossier gauche et dossier droit	
		for (unsigned int i=0; i<repertoiresFils.size() ; i++)
		{
			vectPosFils.push_back(positionnerElements(repertoiresFils[i]));
		}
			ma_position_x=(((int)vectPosFils[vectPosFils.size()-1].x)-((int)vectPosFils[0].x))/2;
			maPosition=Vector3(ma_position_x,f->getProfondeur(),0);
	
			//debug
			oss<<f->getProfondeur();
			debug+="prof racine"+oss.str()+"\n";

			creerEntite(f->getNom(),"CubeRed.mesh",maPosition);	

			//afficherFils(f,maPosition,vectPosFils);

			creerLiensFils(maPosition,vectPosFils);			
	}
	return maPosition;
}

//pointeurs de fonctions getFileNo ou getFolderNo ...

void Visualisation::creerReprTest(char * nomRacine)
{
	//creerRacine("/home/lionel/Desktop/TC5-TER/TestFichiers/","CubeBlue.mesh",Vector3(SCALE,SCALE,SCALE));
	//ratio ground / entite
	myApp->setRatio(100);
	this->racine=myApp->getSceneManager()->getRootSceneNode()->createChildSceneNode("SceneRacine");
	Folder * f = new Folder(nomRacine,0); 
	
	positionnerElements(f);

	afficherMessage(debug);

	//myApp->setSelected(nomRacine);
	construction_finie=true;


	//test de la fonction de repartition
	/*vector<int> vectPos(5);
	repartirElements(1,5,vectPos);
	ostringstream oss; 
	for (unsigned int i=0;i<vectPos.size();i++)
	{
		oss << "elt "<< i << " : " << vectPos[i] << endl;
	}
	afficherMessage(oss.str());

	creerRacine("/home/lionel/Desktop/TC5-TER/TestFichiers/","CubeBlue.mesh",Vector3(SCALE,SCALE,SCALE));
	creerEntite(((*f).getFolderNo(0))->getNom(),"CubeGreen.mesh",Vector3(vectPos[4],1,0));
	ligne(getRacine(),getRacine()->getPosition(),getNoeud(((*f).getFolderNo(0))->getNom())->getPosition());

	for(int i=0;i<4;i++)
	{
		creerEntite(((*f).getFileNo(i))->getNom(),"SphereYellow.mesh",Vector3(vectPos[i],1,0));
		ligne(getRacine(),getRacine()->getPosition(),getNoeud(((*f).getFileNo(i))->getNom())->getPosition());
	}*/
	f=NULL;
}

//fonction pour ajouter un objet a la scene
/*void Visualisation::attachEntity(Entity * entity, SceneNode * sceneNode, Vector3 vScale, Vector3 vTrans)
{
    sceneNode->scale(vScale);
    sceneNode->translate(vTrans);
    sceneNode->attachObject(entity);
}*/

//getters
SceneNode * Visualisation::getNoeud(String name)
{
	return myApp->getSceneManager()->getSceneNode(name);
}

SceneNode * Visualisation::getRacine()
{
	return this->racine;
}

int Visualisation::getDecalage()
{
	return decalage;
}

void Visualisation::setDecalage(int i)
{
	decalage=i;
}

bool Visualisation::getConstructionFinie()
{
	return construction_finie;
}
